package WSePagesImport;
use base WSLinkProducts;
use strict;
use warnings;
use WSLinkProducts;
use DE_EPAGES::Core::API::Log qw (LogDebug GetLog);
use DE_EPAGES::Database::API::Connection qw( GetCurrentDBHandle );
use DE_EPAGES::Object::API::Factory
    qw( LoadObject ExistsObjectByPath LoadObjectByPath Transaction DeleteObject LoadClassByAlias);
use DE_EPAGES::Shop::API::Table::ShopCountry
    qw (GetInfoShopCountriesByShopID InsertShopCountry ExistsShopCountry DeleteShopCountry);
use DE_EPAGES::Object::API::Language qw (GetPKeyLanguageByCode);
use DE_EPAGES::Database::API::Connection qw( RunOnStore );
use DE_EPAGES::Core::API::Script qw( RunScript );
use DE_EPAGES::Product::API::Product
    qw (SubProductFolder JoinVariationValues GetInfoSubProductsBySuperProductID);
use DE_EPAGES::Order::API::Basket qw(GetExistingBasket);
use DE_EPAGES::Product::API::Basket qw( AddProducts );
use DE_EPAGES::Catalog::API::Catalog
    qw (AssignProductToCategory RemoveProductFromCategory);
use DE_EPAGES::Presentation::API::PageCache qw (InvalidatePageCache);
use DE_EPAGES::Core::API::Error qw( Error ExistsError GetError );
use DE_EPAGES::Core::API::Warning qw( Warning );
use DE_EPAGES::WebInterface::API::MessageCenter qw( SynchronizeCache );
use DE_EPAGES::Core::API::Error qw( Error ExistsError GetError );
use Log::Log4perl qw(:easy);
use Data::Dumper;

sub new {
    my $class = $_[0];
    my $self;
    $self = WSLinkProducts->new( $_[1], $_[2], $_[8] );
    $self->{_fieldsAssign}  = $_[3];
    $self->{categoriesList} = $_[4];
    $self->{_shop_path}     = $_[5];
    $self->{_import_mode}   = $_[6];
    $self->{_display}       = $_[7];
    my $shop          = LoadObjectByPath( $self->{_shop_path} );
    my $productFolder = $shop->get('ProductFolder');
    my $categoriesObj
        = LoadObjectByPath( $self->{_shop_path} . '/Categories' );
    my $languageID   = GetPKeyLanguageByCode('en');
    my $taxClassNone = $shop->get('TaxMatrix')->child('none');

#set up variables for later use so we don't end up making the same procedure calls.

    my $importCfg = undef;

    $importCfg = {
        'ProductFolder' => $productFolder,
        'TaxClassNone'  => $taxClassNone,
        'CategoriesObj' => $categoriesObj,
        'LanguageID'    => $languageID,
    };
    my $cfgStatus = 1;
    foreach my $cfg ( keys %$importCfg ) {
        if ( !defined $importCfg->{$cfg} ) {
            $cfgStatus = 0;

            #print "ERROR!!";
            $self->LogFatal(
                "Config elements are missing - can't proceed any further!");
            $importCfg = undef;
            last;
        }
    }
    $self->{importCfg}                    = $importCfg;
    $self->{emptyFields}->{Author}        = 0;
    $self->{emptyFields}->{ProductFormat} = 0;
    $self->{emptyFields}->{ISBN}          = 0;

    #Create ePagesCategories tree before import
    bless $self, $class;
    return $self;
}

sub generateCategoriesList {
    my $self = shift;
    $self->LogInfo("Generating categories structure tree.");
    my $mainCatPath    = "/Categories";
    my $categoriesObj  = $self->{importCfg}->{CategoriesObj};
    my $MainCategories = $categoriesObj->childrenByClass('Category');
    foreach (@$MainCategories) {
        my $flCatName = $_->{'Attributes'}->{'Alias'};
        my $flCatFullPath
            = $self->{_shop_path} . $mainCatPath . "/" . $flCatName;

        #save the category to the list
        $self->{ePagesCategories}->{$flCatName} = $flCatFullPath;

        #drill deeper
        my $SubCatObj     = LoadObjectByPath($flCatFullPath);
        my $SubCategories = $SubCatObj->childrenByClass('Category');
        foreach (@$SubCategories) {
            my $slCatName = $_->{'Attributes'}->{'Alias'};
            my $slCatFullPath
                = $self->{_shop_path}
                . $mainCatPath . "/"
                . $flCatName . "/"
                . $slCatName;

            #save the category to the list
            $self->{ePagesCategories}->{$slCatName} = $slCatFullPath;
            my $SubSubCatObj     = LoadObjectByPath($slCatFullPath);
            my $SubSubCategories = $SubSubCatObj->childrenByClass('Category');
            foreach (@$SubSubCategories) {
                my $tlCatName = $_->{'Attributes'}->{'Alias'};
                my $tlCatFullPath
                    = $self->{_shop_path}
                    . $mainCatPath . "/"
                    . $flCatName . "/"
                    . $slCatName . "/"
                    . $tlCatName;

                #save the category to the list
                $self->{ePagesCategories}->{$tlCatName} = $tlCatFullPath;
                my $SubSubSubCatObj = LoadObjectByPath($tlCatFullPath);
                my $SubSubSubCategories
                    = $SubSubSubCatObj->childrenByClass('Category');
                foreach (@$SubSubSubCategories) {
                    my $folCatName = $_->{'Attributes'}->{'Alias'};
                    my $folCatFullPath
                        = $self->{_shop_path}
                        . $mainCatPath . "/"
                        . $flCatName . "/"
                        . $slCatName . "/"
                        . $tlCatName . "/"
                        . $folCatName;

                    #save the category to the list
                    $self->{ePagesCategories}->{$folCatName}
                        = $folCatFullPath;
                    my $SubSubSubSubCatObj
                        = LoadObjectByPath($folCatFullPath);
                    my $SubSubSubSubCategories
                        = $SubSubSubSubCatObj->childrenByClass('Category');
                    foreach (@$SubSubSubSubCategories) {
                        my $filCatName = $_->{'Attributes'}->{'Alias'};
                        my $filCatFullPath
                            = $self->{_shop_path}
                            . $mainCatPath . "/"
                            . $flCatName . "/"
                            . $slCatName . "/"
                            . $tlCatName . "/"
                            . $folCatName . "/"
                            . $filCatName;

                        #save the category to the list
                        $self->{ePagesCategories}->{$filCatName}
                            = $filCatFullPath;
                    }
                }
            }
        }
    }
    $self->LogInfo( "List of the categories along with full path:\n"
            . Dumper( $self->{ePagesCategories} ) );
    return;
}

sub generateePagesBooksList {
    my ($self) = @_;
    $self->LogInfo("Generating ePages product list.");
    my $productFolder = $self->{importCfg}->{'ProductFolder'};
    my $allProducts   = $productFolder->children();
    for ( my $i = 0; $i < scalar(@$allProducts); $i++ ) {
        $self->{ePagesBooksList}
            ->{ $allProducts->[$i]->{'Attributes'}->{'Alias'} }
            = $allProducts->[$i]->{'Attributes'}->{'ObjectID'};
    }
    return;
}

sub updateePagesBooksList {
    my ( $self, $alias ) = @_;
    delete( $self->{ePagesBooksList}->{$alias} );
    return;
}

sub removeOldePagesBooks {
    my $self      = shift;
    my $start_run = time();
    my $nubmer    = keys %{ $self->{ePagesBooksList} };
    $self->LogInfo(
        "-_ Removing " . $nubmer . " books not covered by imported data." );
    foreach my $key ( keys %{ $self->{ePagesBooksList} } ) {
        my $product
            = LoadObjectByPath( $self->{_shop_path} . '/Products/' . $key );
        my $title = $product->get( 'NameOrAlias',
            $product->get('Site')->get('LanguageID') );
        if ( defined($product) ) {
            DeleteObject( $self->{ePagesBooksList}->{$key} );
        }
        $self->_dispatchScreenInfo( $key, $title, 'DELETE' );
    }
    my $end_run  = time();
    my $run_time = $end_run - $start_run;
    $self->LogInfo( "-_ Removing job took: " . $run_time . " seconds." );
    return;
}

sub importProducts {
    my $self       = shift;
    my $arrRespond = shift;
    my $i          = 0;
    if ( ref($arrRespond) eq "ARRAY" ) {
        $self->LogInfo("Preparing to import a batch of products from ARRAY.");
        for ( $i = 0; $i < scalar(@$arrRespond); $i++ ) {
            $self->LogInfo(
                "Picking up data reckord: " . $i . " from current batch:" );
            $self->LogInfo( $arrRespond->[$i]->{'ProductCode'} . "  "
                    . $arrRespond->[$i]->{'ProductDescription'} );
            $self->_createSuperProduct( $arrRespond->[$i] );
        }
    }
    elsif ( ref($arrRespond) eq "HASH" ) {
        $self->LogInfo("Preparing to import a batch of products from HASH.");
        $self->LogInfo( $arrRespond->{'ProductCode'} . "  "
                . $arrRespond->{'ProductDescription'} );
        $self->_createSuperProduct($arrRespond);
    }
    else {
        $self->LogFatal(
            "The webservice respond is not correct, ARRAY or HASH expected!");
    }
    return $i;
}

sub _extractStockLevel {
    my ( $self, $stockLevel, $newMaster ) = @_;
    my @path = split( ":", $stockLevel );
    return $newMaster->{ $path[0] }->{ $path[1] };
}

sub _extractBookDetails {
    my ( $self, $bookDetails, $newMaster ) = @_;
    my @path = split( ":", $bookDetails );
    return $newMaster->{ $path[0] }->{ $path[1] };
}

sub _extractPublishedPrice {
    my ( $self, $bookDesc ) = @_;
    my @path = split( "<P>", $bookDesc );
    my @price = $path[1] =~ /(\d+\.?\d*)/;
    return $price[0];
}

sub _extractPublishedPriceForAttribute {
    my ( $self, $bookDesc ) = @_;
    my @path  = split( "<P>", $bookDesc );
    my @price = split( " ",   $path[1] );

    #    my @price = $path[1] =~ /(\d+\.?\d*)/;
    if ( $price[0] eq "ONLY" || $price[0] eq "" || $price[0] eq "WAS" ) {
        return "";
    }
    else {

        #        print $price[0] . "\n";
        return $price[0];
    }

}

sub _extractBookDescription {
    my ( $self, $bookDesc ) = @_;
    my @description
        = $bookDesc =~ m/^([\s\S]*)(\<T\>)([\s\S]*)(\<P\>)([\s\S]*)$/;

    #   return $bookDesc;
    return $description[2];
}

sub _incrementIndicator {
    my ( $self, $hashId, $category ) = @_;
    if ( exists $self->{$hashId}->{$category} ) {
        my $counter = $self->{$hashId}->{$category};
        $self->{$hashId}->{$category} += 1;
        return;
    }
    else {
        $self->{$hashId}->{$category} = 1;
        return;
    }
}

sub _countCategories {
    my ( $self, $category ) = @_;
    if ( $category ne "" ) {
        $self->_incrementIndicator( "categories", $category );
    }
    return;
}

sub _fitCategoryName {
    my ( $self, $categoryName ) = @_;
    $categoryName = uc($categoryName);
    $categoryName =~ s/\s/_/g;
    $categoryName =~ s/&/AND/g;
    $categoryName =~ s/\.\.\.//g;
    my @parts = split( "'", $categoryName );
    $categoryName = $parts[0] . $parts[1];
    return $categoryName;

}

sub _createSuperProduct {
    my ( $self, $newMaster ) = @_;
    my $masterID      = $newMaster->{ $self->{_fieldsAssign}->{Alias} };
    my $productFolder = $self->{importCfg}->{'ProductFolder'};
    my $shop          = $productFolder->get('Site');
    my $importStatus;
    my $Author;
    my $ProductFormat;
    my $Description;
    my $ISBN;
    my $unit = LoadObjectByPath("/Units/piece");

    $self->{timeFlag} = time();

    if ( !ExistsObjectByPath( $self->{_shop_path} . "/Products/$masterID" ) )
    {
        my $ProductType = $shop->get('ProductClass');
        my $taxClass    = $self->{importCfg}->{TaxClassNone};

        if ( !defined $taxClass ) {
            $self->LogFatal(
                "Tax Class is not defined WTF? - product can not be imported."
            );
            return;
        }

        my $SuperProduct = undef;

        #--- create super product
        eval {
            $SuperProduct = $productFolder->insertChild(
                $ProductType,
                {   'Alias'       => $masterID,
                    'IsAvailable' => 1,
                    'IsVisible'   => 1,
                    'TaxClass'    => $taxClass
                }
            );
        };

        if ( ExistsError() ) {
            $self->LogError(
                "The product cannot be added - perhaps it already exist?");
            $importStatus = "FAIL";
        }
        else {
            if ( defined $SuperProduct ) {
                $self->LogInfo("$masterID - The product has been added.");

                #my $SubProds = $newMaster->{'SubProducts'};
                $Description = $self->_extractBookDescription(
                    $newMaster->{ $self->{_fieldsAssign}->{Description} } );
                if ( !$Description ) {
                    $Description = " ";
                    $self->{emptyFields}->{Description}++;
                }

                $SuperProduct->set(
                    {   'Name' =>
                            $newMaster->{ $self->{_fieldsAssign}->{Name} }
                    },
                    $self->{importCfg}->{'LanguageID'}
                );
                $SuperProduct->set(
                    { 'Description' => $Description },
                    $self->{importCfg}->{'LanguageID'}
                );
                $SuperProduct->set(
                    { 'Text' => $Description },
                    $self->{importCfg}->{'LanguageID'}
                );
                $SuperProduct->set( { 'OrderUnit' => $unit },
                    $self->{importCfg}->{'LanguageID'} );
                $SuperProduct->setListPrice( 'GBP', 1,
                    $newMaster->{ $self->{_fieldsAssign}->{Price} } );

#ManufacturerPrice uses store currency - in case of the customer
# we sometimes need to use also alternative currency
# therefore I replaced this bit:
#                $SuperProduct->setManufacturerPrice(
#                    'GBP', 1,
#                    $self->_extractPublishedPrice(
#                        $newMaster->{ $self->{_fieldsAssign}->{Description} }
#                    )
#                );
#with:

                $SuperProduct->set(
                    {   'PriceCompare' =>
                            $self->_extractPublishedPriceForAttribute(
                            $newMaster->{ $self->{_fieldsAssign}
                                    ->{Description} }
                            )
                    }
                );

                #End of changes.

                my $stockLevelINT = $self->_extractStockLevel(
                    $self->{_fieldsAssign}->{StockLevel}, $newMaster );

                #	 If This is product SellRegardlessStockLevel
                if ( $stockLevelINT == 0 ) {

                    #	print "STOCK LEVEL ZEEEEROOOOOOOOOOOO!!!!!!!!";
                    $SuperProduct->set( { 'SellRegardlessStockLevel' => 1 } );
                    $SuperProduct->set( { 'StockLevel' => 99999 } );
                }
                else {
                    $SuperProduct->set( { 'SellRegardlessStockLevel' => 0 } );
                    $SuperProduct->set( { 'StockLevel' => $stockLevelINT } );
                }

                $Author = $self->_extractBookDetails(
                    $self->{_fieldsAssign}->{Author}, $newMaster );
                $ProductFormat = $self->_extractBookDetails(
                    $self->{_fieldsAssign}->{ProductFormat}, $newMaster );
                $ISBN = $self->_extractBookDetails(
                    $self->{_fieldsAssign}->{ISBN}, $newMaster );

                if ( !$Author || $Author eq "" ) {
                    $Author = "Unknown";
                    $self->{emptyFields}->{Author}++;
                }
                if ( !$ProductFormat || $ProductFormat eq "" ) {
                    $ProductFormat = "Unknown";
                    $self->{emptyFields}->{ProductFormat}++;
                }
                if ( !$ISBN || $ISBN eq "" ) {
                    $ISBN = "Unknown";
                    $self->{emptyFields}->{ISBN}++;
                }

                $SuperProduct->set( { 'Author'        => $Author } );
                $SuperProduct->set( { 'ProductFormat' => $ProductFormat } );
                $SuperProduct->set( { 'ISBN'          => $ISBN } );
                $SuperProduct->set(
                    {   'ManufacturerSKU' => $self->_extractBookDetails(
                            $self->{_fieldsAssign}->{ManufacturerSKU},
                            $newMaster
                        )
                    }
                );
                $SuperProduct->set(
                    {   'Manufacturer' => $self->_extractBookDetails(
                            $self->{_fieldsAssign}->{Manufacturer}, $newMaster
                        )
                    }
                );

                #Do stuff with the categories
                for (
                    my $i = 0;
                    $i < scalar( @{ $self->{categoriesList} } );
                    $i++
                    )
                {
                    my $preparedCategoryName = $self->_fitCategoryName(
                        $self->_extractBookDetails(
                            $self->{_fieldsAssign}
                                ->{ $self->{categoriesList}->[$i] },
                            $newMaster
                        )
                    );
                    $self->_countCategories($preparedCategoryName);
                    if ( $self->{ePagesCategories}->{$preparedCategoryName} )
                    {
                        my $categoryObject
                            = LoadObjectByPath( $self->{ePagesCategories}
                                ->{$preparedCategoryName} );
                        AssignProductToCategory( $SuperProduct,
                            $categoryObject );
                    }
                    else {
                        $self->_incrementIndicator( "nonExistentCategories",
                            $preparedCategoryName );
                    }
                }

                $importStatus = "OK";
            }
            else {
                $self->LogError(
                    "$masterID - Product is not in the DB, attributes can't be added."
                );
                $importStatus = "FAIL";
            }
        }

    }
    else {
        if ( $self->{_import_mode} eq "add" ) {
            $self->LogError(
                "The product cannot be added - It is already in store DB.");
            $importStatus = "SKIPED";
        }
        elsif ( $self->{_import_mode} eq "update" ) {
            my $updateProduct = LoadObjectByPath(
                $self->{_shop_path} . "/Products/$masterID" );

            $Description = $self->_extractBookDescription(
                $newMaster->{ $self->{_fieldsAssign}->{Description} } );
            if ( !$Description ) {
                $Description = " ";
                $self->{emptyFields}->{Description}++;
            }

            $updateProduct->set(
                { 'Name' => $newMaster->{ $self->{_fieldsAssign}->{Name} } },
                $self->{importCfg}->{'LanguageID'}
            );
            $updateProduct->set(
                { 'Description' => $Description },
                $self->{importCfg}->{'LanguageID'}
            );
            $updateProduct->set(
                { 'Text' => $Description },
                $self->{importCfg}->{'LanguageID'}
            );
            $updateProduct->set( { 'OrderUnit' => $unit },
                $self->{importCfg}->{'LanguageID'} );
            $updateProduct->setListPrice( 'GBP', 1,
                $newMaster->{ $self->{_fieldsAssign}->{Price} } );

    #ManufacturerPrice uses store currency - in case of Bibliophile
    # we sometimes need to use also alternative currency
    # therefore I replaced this bit:
    #            $updateProduct->setManufacturerPrice(
    #                'GBP', 1,
    #                $self->_extractPublishedPrice(
    #                    $newMaster->{ $self->{_fieldsAssign}->{Description} }
    #                )
    #            );
    #with:
            $updateProduct->set(
                {   'PriceCompare' =>
                        $self->_extractPublishedPriceForAttribute(
                        $newMaster->{ $self->{_fieldsAssign}->{Description} }
                        )
                }
            );

            #End of changes

            my $stockLevelINT = $self->_extractStockLevel(
                $self->{_fieldsAssign}->{StockLevel}, $newMaster );

            #			    If This is product SellRegardlessStockLevel
            if ( $stockLevelINT == 0 ) {

                # print "STOCK LEVEL ZEEEEROOOOOOOOOOOO!!!!!!!!";
                $updateProduct->set( { 'SellRegardlessStockLevel' => 1 } );
                $updateProduct->set( { 'StockLevel' => 99999 } );
            }
            else {
                $updateProduct->set( { 'SellRegardlessStockLevel' => 0 } );
                $updateProduct->set( { 'StockLevel' => $stockLevelINT } );
            }

            $updateProduct->set( { 'IsAvailable' => 1 } );
            $updateProduct->set( { 'IsVisible'   => 1 } );

            $Author = $self->_extractBookDetails(
                $self->{_fieldsAssign}->{Author}, $newMaster );
            $ProductFormat = $self->_extractBookDetails(
                $self->{_fieldsAssign}->{ProductFormat}, $newMaster );
            $ISBN
                = $self->_extractBookDetails( $self->{_fieldsAssign}->{ISBN},
                $newMaster );

            if ( !$Author || $Author eq "" ) {
                $Author = "Unknown";

                #print "AUTHOR EMPTY\n";
                $self->{emptyFields}->{Author}++;
            }
            if ( !$ProductFormat || $ProductFormat eq "" ) {
                $ProductFormat = "Unknown";

                #print "PRODUCTF EMPTY\n";
                $self->{emptyFields}->{ProductFormat}++;
            }
            if ( !$ISBN || $ISBN eq "" ) {
                $ISBN = "Unknown";

                #print "ISBN EMPTY\n";
                $self->{emptyFields}->{ISBN}++;
            }

            $updateProduct->set( { 'Author'        => $Author } );
            $updateProduct->set( { 'ProductFormat' => $ProductFormat } );
            $updateProduct->set( { 'ISBN'          => $ISBN } );
            $updateProduct->set(
                {   'ManufacturerSKU' => $self->_extractBookDetails(
                        $self->{_fieldsAssign}->{ManufacturerSKU}, $newMaster
                    )
                }
            );
            $updateProduct->set(
                {   'Manufacturer' => $self->_extractBookDetails(
                        $self->{_fieldsAssign}->{Manufacturer}, $newMaster
                    )
                }
            );

            #Do stuff with the categories
            #FIRST REMOVE CATEGORY ASSIGNMENT
            my $tempCurrCategories = $updateProduct->get('Categories');
            for ( my $i = 0; $i < scalar(@$tempCurrCategories); $i++ ) {
                my $oneOfTheCategories = $tempCurrCategories->[$i];
                RemoveProductFromCategory( $updateProduct,
                    $oneOfTheCategories );
            }

            #SECOND ASSIGN TO THE SELECTED CATEGORIES
            for (
                my $i = 0;
                $i < scalar( @{ $self->{categoriesList} } );
                $i++
                )
            {
                my $preparedCategoryName = $self->_fitCategoryName(
                    $self->_extractBookDetails(
                        $self->{_fieldsAssign}
                            ->{ $self->{categoriesList}->[$i] },
                        $newMaster
                    )
                );
                $self->_countCategories($preparedCategoryName);
                if ( $self->{ePagesCategories}->{$preparedCategoryName} ) {
                    my $categoryObject = LoadObjectByPath(
                        $self->{ePagesCategories}->{$preparedCategoryName} );
                    my $ssw = AssignProductToCategory( $updateProduct,
                        $categoryObject );
                }
                else {
                    $self->_incrementIndicator( "nonExistentCategories",
                        $preparedCategoryName );
                }
            }

            $self->LogError(
                "The product had been in store DB, now it is updated.");
            $importStatus = "UPDATE";
        }
        else {
            $self->LogError(
                "The product cannot be added - It is already in store DB.");
            $importStatus = "SKIPED";
        }
    }
    $self->updateePagesBooksList($masterID);

    #update lost of products to be deleted
    $self->_dispatchScreenInfo( $masterID,
        $newMaster->{ $self->{_fieldsAssign}->{Name} },
        $importStatus );
}

sub _dispatchScreenInfo {
    my ( $self, $masterID, $title, $importStatus ) = @_;
    if ( $self->{_display} eq "verbose" ) {
        my $status = "[" . $importStatus . "]";
        format = 
 @<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @||||||||
$masterID, $title, $status 
.
        write;
    }
}

sub hitMe {
    my ( $self, $page ) = @_;
    if ( $self->{_display} eq "verbose" ) {
        print "Chapter: " . $page . "\n";
    }
    my $hitRespond = $self->_hitMe($page);
    return $hitRespond;
}

1;
